﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Media;
using System.Xml.Linq;
using System.Xml.XPath;
using CuteRibs.MVVMLib;
using CuteRibs.WowArmory.ViewModels;

namespace CuteRibs.WowArmory
{
	public class SearchResult
	{
		public Dictionary<string, string> Summary { get; set; }

		protected XDocument XDocument { get; set; }

		public SearchResult() { }

		public SearchResult(string xhtml)
		{
			this.Initialize(xhtml);
		}

		protected virtual bool Initialize(string xhtml)
		{
			if (string.IsNullOrWhiteSpace(xhtml))
			{
				return false;
			}

			this.XDocument = XDocument.Parse(xhtml.Replace(" xmlns=\"http://www.w3.org/1999/xhtml\"", string.Empty));
			var lines = this.XDocument.XPathSelectElements("//ul[@id='menu-search']/li/a").Skip(1);

			if (!lines.Any())
			{
				return false;
			}

			this.Summary = new Dictionary<string, string>();

			foreach (var line in lines)
			{
				var href = line.Attribute("href").Value;
				var index = href.LastIndexOf('=');
				var field = href.Substring(index + 1);
				this.Summary.Add(field, line.Value);
			}

			return true;
		}
	}

	public class SearchResult<T> : SearchResult
		where T : class
	{
		public int PageNumber { get; set; }
		public int PageCount { get; set; }
		public List<T> Items { get; set; }

		public SearchResult(string xhtml) : base(xhtml) { }

		protected override bool Initialize(string xhtml)
		{
			if (!base.Initialize(xhtml))
			{
				return false;
			}

			var result = this.XDocument.XPathSelectElement("//div[@class='search-right']");
			var pagination = result.XPathSelectElements("//ul[@class='ui-pagination']").Last();
			var page = pagination.XPathSelectElement("li[@class='current']");

			this.PageNumber = Convert.ToInt32(pagination.XPathSelectElement("li[@class='current']").Attribute("data-pagenum").Value);
			this.PageCount = pagination.XPathSelectElements("li/a[@data-pagenum]").Select(e => Convert.ToInt32(e.Attribute("data-pagenum").Value)).Max();

			return true;
		}

		internal static SolidColorBrush GetClassColor(string classIcon)
		{
			var classNumber = classIcon.Substring(classIcon.LastIndexOf('_') + 1).Replace(".jpg", string.Empty);
			return App.GetClassColor(classNumber);
		}

		internal static SolidColorBrush GetSideColor(string sideIcon)
		{
			var side = sideIcon.Substring(sideIcon.LastIndexOf('_') + 1).Replace(".jpg", string.Empty);
			return App.GetSideColor(side);
		}
	}

	public class CharacterSearchResult : SearchResult<CharacterSearchResultViewModel>
	{
		public CharacterSearchResult(string xhtml)
			: base(xhtml) { }

		protected override bool Initialize(string xhtml)
		{
			if (!base.Initialize(xhtml))
			{
				return false;
			}

			var tbody = this.XDocument.XPathSelectElement("//div[@class='view-table']//tbody");
			this.Items = new List<CharacterSearchResultViewModel>();

			foreach (var tr in tbody.Elements())
			{
				var character = new CharacterSearchResultViewModel();
				var tds = tr.Elements();
				character.Icon = tds.ElementAt(0).Descendants("img").First().Attribute("src").Value;
				character.Name = tds.ElementAt(0).Descendants("strong").First().Value;
				character.Level = tds.ElementAt(1).Value;
				character.Race = tds.ElementAt(2).Descendants("span").First().Attribute("data-tooltip").Value;
				character.Class = tds.ElementAt(3).Descendants("span").First().Attribute("data-tooltip").Value;
				character.ClassColor = GetClassColor(tds.ElementAt(3).Descendants("img").First().Attribute("src").Value);
				character.Side = tds.ElementAt(4).Descendants("span").First().Attribute("data-tooltip").Value;
				character.SideColor = GetSideColor(tds.ElementAt(4).Descendants("img").First().Attribute("src").Value);
				character.Guild = tds.ElementAt(5).Descendants("a").First().Value;
				character.Realm = tds.ElementAt(6).Value;
				this.Items.Add(character);
			}

			return true;
		}
	}

	public class GuildSearchResult : SearchResult<GuildSearchResultViewModel>
	{
		public GuildSearchResult(string xhtml)
			: base(xhtml) { }

		protected override bool Initialize(string xhtml)
		{
			if (!base.Initialize(xhtml))
			{
				return false;
			}

			var tbody = this.XDocument.XPathSelectElement("//div[@class='view-table']//tbody");
			this.Items = new List<GuildSearchResultViewModel>();

			foreach (var tr in tbody.Elements())
			{
				var guild = new GuildSearchResultViewModel();
				var tds = tr.Elements();
				guild.Name = tds.ElementAt(0).Descendants("strong").First().Value;
				guild.Realm = tds.ElementAt(1).Value;
				guild.BattleGroup = tds.ElementAt(2).Value;
				guild.Side = tds.ElementAt(3).Descendants("span").First().Attribute("data-tooltip").Value;
				guild.SideColor = GetSideColor(tds.ElementAt(3).Descendants("img").First().Attribute("src").Value);
				guild.Level = tds.ElementAt(4).Value;
				this.Items.Add(guild);
			}

			return true;
		}
	}

	public class ItemSearchResult : SearchResult<ItemSearchResultViewModel>
	{
		public ItemSearchResult(string xhtml)
			: base(xhtml) { }

		protected override bool Initialize(string xhtml)
		{
			if (!base.Initialize(xhtml))
			{
				return false;
			}

			var tbody = this.XDocument.XPathSelectElement("//div[@class='view-table']//tbody");
			this.Items = new List<ItemSearchResultViewModel>();

			foreach (var tr in tbody.Elements())
			{
				var item = new ItemSearchResultViewModel();
				var tds = tr.Elements();
				item.Name = tds.ElementAt(0).Descendants("strong").First().Value;

				var a = tds.ElementAt(0).Descendants("a").First();
				var str = a.Attribute("href").Value;
				item.Id = str.Substring(str.LastIndexOf('/') + 1);
				str = a.Attribute("class").Value;
				item.Quality = str.Substring(str.LastIndexOf('q') + 1);
				item.QualityColor = App.GetItemColor(item.Quality);
				str = tds.ElementAt(0).Descendants("span").First().Attribute("style").Value;
				item.Icon = str.Remove(str.LastIndexOf('.')).Substring(str.LastIndexOf('/') + 1);
				item.ItemLevel = tds.ElementAt(1).Value.Trim();
				item.RequiredLevel = tds.ElementAt(2).Value.Trim();
				item.InventoryType = tds.ElementAt(4).FirstNode.ToString().Trim();
				var em = tds.ElementAt(4).Element("em");
				item.EquipmentType = em == null ? string.Empty : em.Value.Trim();
				this.Items.Add(item);
			}

			return true;
		}
	}

	public class ArenaTeamSearchResult : SearchResult<ArenaTeamSearchResultItemViewModel>
	{
		public ArenaTeamSearchResult(string xhtml)
			: base(xhtml) { }

		protected override bool Initialize(string xhtml)
		{
			if (!base.Initialize(xhtml))
			{
				return false;
			}

			var tbody = this.XDocument.XPathSelectElement("//div[@class='view-table']//tbody");
			this.Items = new List<ArenaTeamSearchResultItemViewModel>();

			foreach (var tr in tbody.Elements())
			{
				var team = new ArenaTeamSearchResultItemViewModel();
				var tds = tr.Elements();
				team.Name = tds.ElementAt(0).Descendants("strong").First().Value;
				team.Side = tds.ElementAt(1).Value;
				team.Realm = tds.ElementAt(2).Value;
				team.BattleGroup = tds.ElementAt(3).Value;
				team.Side = tds.ElementAt(4).Descendants("span").First().Attribute("data-tooltip").Value;
				team.SideColor = GetSideColor(tds.ElementAt(4).Descendants("img").First().Attribute("src").Value);
				team.Rating = tds.ElementAt(5).Value;
				this.Items.Add(team);
			}

			return true;
		}
	}

	public class ContentSearchResult : SearchResult<ContentSearchResultViewModel>
	{
		public ContentSearchResult(string xhtml)
			: base(xhtml) { }

		protected override bool Initialize(string xhtml)
		{
			if (!base.Initialize(xhtml))
			{
				return false;
			}

			var list = this.XDocument.XPathSelectElement("//div[@class='view-list']");
			this.Items = new List<ContentSearchResultViewModel>();

			foreach (var item in list.Elements())
			{
				var content = new ContentSearchResultViewModel();
				XElement el;

				if ((el = item.XPathSelectElement("a[@class='thumbnail']/span/img")) != null)
				{
					content.Icon = el.Attribute("src").Value;
				}

				if ((el = item.XPathSelectElement("h4/a")) != null)
				{
					content.Link = el.Attribute("href").Value;
					content.Title = el.Value.Trim();
				}

				if ((el = item.XPathSelectElement("div[@class='meta']")) != null)
				{
					content.Category = el.FirstNode.ToString().Trim();
					content.Tags = el.Elements().Select(e => e.Value).Aggregate((n, i) => i + ", " + n);
				}

				if ((el = item.XPathSelectElement("div[@class='content']")) != null)
				{
					content.Description = el.Value.Trim();
				}

				this.Items.Add(content);
			}

			return true;
		}
	}

	public class ForumSearchResult : SearchResult<ForumSearchResultViewModel>
	{
		public ForumSearchResult(string xhtml)
			: base(xhtml) { }

		protected override bool Initialize(string xhtml)
		{
			if (!base.Initialize(xhtml))
			{
				return false;
			}

			var list = this.XDocument.XPathSelectElement("//div[@class='view-list']");
			this.Items = new List<ForumSearchResultViewModel>();

			foreach (var item in list.Elements())
			{
				var forum = new ForumSearchResultViewModel();
				XElement el;

				if ((el = item.XPathSelectElement("h4/span[contains(@class,'status')]")) != null)
				{
					forum.IsReply = true;
				}

				if ((el = item.XPathSelectElement("h4/a")) != null)
				{
					forum.PostLink = el.Attribute("href").Value;
					forum.Title = el.Value.Trim();
					forum.Replies = el.NextNode.ToString().Trim();
				}

				if ((el = item.XPathSelectElement("div[@class='meta']/a[@class='sublink']")) != null)
				{
					forum.ForumLink = el.Attribute("href").Value;
					forum.Forum = el.Value.Trim();
				}

				if ((el = item.XPathSelectElement("div[@class='meta']/a[@class='author']")) != null)
				{
					forum.Author = el.Value.Trim();
					forum.DateTime = el.NextNode.ToString().Trim();
				}

				if ((el = item.XPathSelectElement("div[@class='content']")) != null)
				{
					forum.Brief = el.Value.Trim();
				}

				this.Items.Add(forum);
			}

			return true;
		}
	}

	public class BlogSearchResult : SearchResult<BlogSearchResultViewModel>
	{
		public BlogSearchResult(string xhtml)
			: base(xhtml) { }

		protected override bool Initialize(string xhtml)
		{
			if (!base.Initialize(xhtml))
			{
				return false;
			}

			var list = this.XDocument.XPathSelectElement("//div[@class='view-list']");
			this.Items = new List<BlogSearchResultViewModel>();

			foreach (var item in list.Elements())
			{
				var blog = new BlogSearchResultViewModel();
				XElement el;

				if ((el = item.XPathSelectElement("a[@class='thumbnail']/span/img")) != null)
				{
					blog.Icon = el.Attribute("src").Value;
				}

				if ((el = item.XPathSelectElement("h4/a")) != null)
				{
					blog.Link = el.Attribute("href").Value;
					blog.Title = el.Value.Trim();
					blog.Comments = el.NextNode.ToString().Trim();
				}

				if ((el = item.XPathSelectElement("div[@class='meta']/a")) != null)
				{
					blog.Author = el.Value.ToString().Trim();
					blog.DateTime = el.NextNode.ToString().Trim();
				}

				if ((el = item.XPathSelectElement("div[@class='content']")) != null)
				{
					blog.Brief = el.Value.Trim();
				}

				this.Items.Add(blog);
			}

			return true;
		}
	}

	public class SupportSearchResult : SearchResult<SupportSearchResultViewModel>
	{
		public SupportSearchResult(string xhtml)
			: base(xhtml) { }

		protected override bool Initialize(string xhtml)
		{
			if (!base.Initialize(xhtml))
			{
				return false;
			}

			var list = this.XDocument.XPathSelectElement("//div[@class='view-list']");
			this.Items = new List<SupportSearchResultViewModel>();

			foreach (var item in list.Elements())
			{
				var support = new SupportSearchResultViewModel();
				XElement el;

				if ((el = item.XPathSelectElement("h4/a")) != null)
				{
					support.Link = el.Attribute("href").Value;
					support.Title = el.Value.Trim();
				}

				if ((el = item.XPathSelectElement("div[@class='content']")) != null)
				{
					support.Brief = el.Value.Trim();
				}

				if ((el = item.XPathSelectElement("div[@class='meta'][1]")) != null)
				{
					support.DateTime = el.Value.Trim();
				}

				if ((el = item.XPathSelectElement("div[@class='meta'][2]")) != null)
				{
					support.Keywords = el.Elements("a").Select(e => e.Value).Aggregate((n, i) => i + ", " + n);
				}

				this.Items.Add(support);
			}

			return true;
		}
	}
}
